package com.fdb.efp.cus.api.rest;

import com.alibaba.fastjson.JSON;
import com.gdrcu.efp.cus.common.CusRelCheckEnum;
import com.gdrcu.efp.cus.common.ExcelException;
import com.gdrcu.efp.cus.common.util.ExcelImportUtil;
import com.fdb.basic.framework.core.constant.ApplicationConstance;
import com.fdb.basic.framework.core.constant.ResponseData;
import com.fdb.basic.framework.core.constant.SDicCertTypeEnum;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.util.MD5Util;
import com.fdb.basic.framework.core.util.MessageRuleCheckUtil;
import com.fdb.basic.framework.core.util.StringUtil;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.web.controller.AbstractController;
import com.fdb.basic.sequence.service.facade.SequenceService;
import com.fdb.efp.cus.api.common.CusEnums;
import com.fdb.efp.cus.service.facade.CusRelCheckService;
import com.fdb.efp.cus.service.vo.CusRelCheckExcelVO;
import com.fdb.efp.cus.service.vo.CusRelCheckVO;
import com.fdb.efp.e4a.service.facade.SRoleDataRuleService;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 关联人信息controller
 * @author qiuyf
 * @since 2018年12月28日 上午10:41:57
 * @version 1.0
 */
@RestController
@RequestMapping("/api")
public class CusRelCheckController extends AbstractController{


	@Autowired
	@Qualifier("sRoleDataRuleService")
	private SRoleDataRuleService sRoleDataRuleService;


	@Autowired
	@Qualifier("cusRelCheckService")
	private CusRelCheckService cusRelCheckService;

	@Autowired
	@Qualifier("dbSeqService")
	private SequenceService sequenceService;

	private static Logger logger = LoggerFactory.getLogger(CusRelCheckController.class);

	private static final String CONTENTTYPE = "application/json;charset=UTF-8"; 

	private static final String MODELNAME = "自然人关联人导入模板.xls";

	private static final String SHEET1NAME = "自然人关联人";

	private static final String IMPORT_PATH = "/template/importTemplate.xls";

	private List<CusRelCheckExcelVO> errorHisDuplicateDataList = new ArrayList<>();

	private List<CusRelCheckExcelVO> singleRowList = new ArrayList<>();

	@RequestMapping(value="/cus/relChecks", method=RequestMethod.POST)
	public @ResponseBody ResponseData<List<CusRelCheckVO>> queryCusRelCheckAll(@RequestBody CusRelCheckVO vo) {	

		if(CusEnums.cusRelRelation.REL_RELATION_01.getValue().equals(vo.getRelRelation())) {
			String cusName = vo.getCusName();//姓名
			String certCode = vo.getCertCode();//证件号码
			if(!StringUtil.isNullorBank(cusName)) {
				vo.setCusName(MD5Util.getMD5ofStr(cusName).toUpperCase());//加密姓名
			}
			if(!StringUtil.isNullorBank(certCode)) {
				vo.setCertCode(MD5Util.getMD5ofStr(certCode).toUpperCase());//加密证件号码
			}
		}
		List<CusRelCheckVO> outputVo = new ArrayList<>();
		if (!StringUtil.isNullorBank(vo.getExportFlag()) && "exp".equals(vo.getExportFlag())) {
			outputVo = cusRelCheckService.queryExCusRelCheckPageInfo(vo);
		} else if (StringUtil.isNullorBank(vo.getExportFlag())){
			outputVo = cusRelCheckService.queryCusRelCheckPageInfo(vo);
		}
		outputVo = this.dealResultShow(outputVo);
		return getResponseData(outputVo);
	}

	/**
	 * 关联人模板下载
	 * @author  qiuyf
	 * @since 2019年3月20日 下午6:05:19
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	@RequestMapping(value="/cus/rel/downLoad", method=RequestMethod.GET)
	public @ResponseBody ResponseData<String> cusRelCherkModelDownLoad(HttpServletResponse response, HttpServletRequest request) throws IOException {
		BufferedInputStream bis = null;
		BufferedOutputStream bos = null;
		try {
			response.setContentType(CONTENTTYPE);
			/**
			 * getBytes()，需要声明一下读取的编码方式，不然IE浏览器，会出现文件名乱码，谷歌不会
			 * 【解决方法】 getBytes("GBK")
			 */
			response.setHeader("Content-Disposition", "attachment;filename="+  new String((MODELNAME).getBytes("GBK"), "ISO8859-1"));
			ServletOutputStream out = response.getOutputStream();
			logger.info("下载关联人数据导入模板开始----------------------------");
			bis = new BufferedInputStream(CusRelCheckController.class.getClassLoader().getResourceAsStream(IMPORT_PATH));
			bos = new BufferedOutputStream(out);
			byte[] buff = new byte[2048];
			int bytesRead;
			while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
				bos.write(buff, 0, bytesRead);
			}
		} catch (Exception e) {
			logger.error("关联人模板文件下载失败：" , e);
			return getResponseData(null);
		} finally {
			if(null != bis) {
				bis.close();
			}
			if(null != bos){
				bos.close();
			}
		}
		logger.info("下载关联人数据导入模板结束。。。。。。。。。。。。。。。。。。。");
		return getResponseData("success!");
	}

	/**
	 * 文件导入并解析储存到数据表
	 * @author  qiuyf
	 * @since 2019年3月22日 上午10:51:10
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	@SuppressWarnings("resource")
	@RequestMapping(value="/cus/rel/upload", method=RequestMethod.POST)
	public void  cusRelCheckListUpload(HttpServletResponse respone, HttpServletRequest request) {
		ResponseData<List<CusRelCheckVO>> result = new ResponseData<List<CusRelCheckVO>>();
		List<File> cusRelChecks = new ArrayList<File>();
		respone.setContentType(CONTENTTYPE);
		OutputStream out = null;
		int total = 0;
		int illegal = 0;
		int repeatNum = 0;
		try {
			out = respone.getOutputStream();
			//获取文件
			cusRelChecks = getFileList(request);
			if(!cusRelChecks.isEmpty()){
				for(File file : cusRelChecks){
					/**
					 * 将Excel文件解析成对应实体Bean
					 */
					List<CusRelCheckExcelVO> cusRelCheckExcelVOList = ExcelImportUtil.importExcelByClass(SHEET1NAME, file, CusRelCheckExcelVO.class);
					//检查导入的数据是否填写错误
//					checkExcelDatas(cusRelCheckExcelVOList);
					//检查历史数据是否重复
					String errStr = "";
					errStr = checkHisDatas(cusRelCheckExcelVOList);
					//组装数据
					List<CusRelCheckVO> inserCusRelCkstBatch = new ArrayList<CusRelCheckVO>();
					inserCusRelCkstBatch =  assembleData(singleRowList);
					//批量插入
					//执行插入操作
					int num = 0;
					if (inserCusRelCkstBatch.size() > 0) num = execBatchInsertSql(inserCusRelCkstBatch);
					if (num < 0) throw new Exception("插入数据出错！");
					//错误信息
					if (!StringUtil.isNullorBank(errStr)) {
						errStr = "ExcelError:" + errStr;
						throw new Exception(errStr);
					}
					//组装结果
					result = getResponseData(inserCusRelCkstBatch);
					/*if(null!=cusRelCheckExcelVOList && !cusRelCheckExcelVOList.isEmpty()){
						total = cusRelCheckExcelVOList.size();
						*//**
						 * 过滤null、空字符串、不合规的身份证号
						 *//*
						cusRelCheckExcelVOList = this.filterCusRelCheck(cusRelCheckExcelVOList);
						//计算存在不合法的数据
						illegal = total - cusRelCheckExcelVOList.size();

						repeatNum = this.insertCusRelCheckData(cusRelCheckExcelVOList);
						if(repeatNum > 0) {
							if(illegal == 0) {
								result = result.createData(inserCusRelCkstBatch, ApplicationConstance.SUCCESS, "成功导入：" + (total-repeatNum) +"条；导入失败条数为："+repeatNum, true);
							}else {
								result = result.createData(inserCusRelCkstBatch, ApplicationConstance.SUCCESS, "成功导入："+(total-illegal-repeatNum)+"条；存在身份证号不合法条数为："+ 
										illegal + "导入失败条数为："+repeatNum, true);
							}
						}else {
							if(illegal == 0) {
								result = getResponseData(inserCusRelCkstBatch);
							}else {
								result = result.createData(inserCusRelCkstBatch, ApplicationConstance.SUCCESS, "成功导入："+(total-illegal)+"条；存在身份证号不合法条数为："+illegal, true);
							}
						}

					}else{
						throw new ExcelException("从文件获取数据为空!");
					}*/
				}
			}else{
				throw new ExcelException("获取不到上传的文件！");
			}
		} catch (Exception e) {
			logger.error("文件上传失败,失败原因:", e);
			result = result.createData(null, ApplicationConstance.FAILURE, e.getMessage(), false);
		} finally {
			String str = JSON.toJSONString(result);
			try {
				out.write(str.getBytes(Charset.forName("UTF-8")));
				out.flush();
				out.close();
			} catch (IOException e) {
				logger.error("关闭数据流OutputStream出错，错误信息为：", e);
			}
		}
	}

	private void checkExcelDatas(List<CusRelCheckExcelVO> cusRelCheckExcelVOList) {

	}

	private int execBatchInsertSql(List<CusRelCheckVO> inserCusRelCkstBatch) {
		int num = 0;
		return num = cusRelCheckService.batchInsertRelCheck(inserCusRelCkstBatch);
	}

	private List<CusRelCheckVO> assembleData(List<CusRelCheckExcelVO> cusRelCheckExcelVO) throws Exception {
		List<CusRelCheckVO> list = new ArrayList<>();
		if (Objects.nonNull(cusRelCheckExcelVO)) {
			Iterator<CusRelCheckExcelVO> iterator = cusRelCheckExcelVO.iterator();
			while(iterator.hasNext()) {
				CusRelCheckExcelVO tempExcelVO = iterator.next();
				CusRelCheckVO cusRelCheckVO = new CusRelCheckVO();
				//设置流水号
				cusRelCheckVO.setRelSerno(sequenceService.getSequence("CUS_REL_SERNO", null, null));
				//设置姓名
				cusRelCheckVO.setCusName(tempExcelVO.getCusName());
				//设置证件类型【需求只有居民身份证】
				cusRelCheckVO.setCertType(SDicCertTypeEnum.IDCARD.getValue());
				//设置证件号码
				cusRelCheckVO.setCertCode(tempExcelVO.getCertCode());
				//设置关联关系为  02  ： 关联人
				cusRelCheckVO.setRelRelation(CusRelCheckEnum.CusRelRelation.CUS_ASSOCIATES.getValue());
				//设置银监会标准
				cusRelCheckVO.setCbrcStandard(tempExcelVO.getCbrcStandard());
				//设置录入时间
				cusRelCheckVO.setCreateTime(TimeUtil.getCurrentDateTime());
				list.add(cusRelCheckVO);
			}
		} else {
			throw new ExcelException("获取数据为空!");
		}
		return list;
	}

	private String checkHisDatas(List<CusRelCheckExcelVO> cusRelCheckExcelVOList) throws Exception {
		int errorRow = 4;
		List<Integer> errorDuplicateRowList = new ArrayList<>();
		String errorDuplicateMsg = "";
		errorHisDuplicateDataList.clear();
		Map<Integer, String> errorList = new HashMap<Integer, String>();

		for (CusRelCheckExcelVO item : cusRelCheckExcelVOList) {
			boolean flag = checkDataIsUnique(item);
			if (flag) {
				errorDuplicateRowList.add(errorRow);
				errorHisDuplicateDataList.add(item);
			}
			errorRow += 1;
		}

		//收集没问题的导入数据
		singleRowList.clear();
		singleRowList = cusRelCheckExcelVOList.stream().filter(a->!errorHisDuplicateDataList.contains(a)).collect(Collectors.toList());

		if (errorDuplicateRowList.size() > 0) {
			for (Integer integer : errorDuplicateRowList) {
				errorDuplicateMsg =  "第【" + integer + "】行，该客户已存在，跳过该条数据！";
				errorList.put(integer, errorDuplicateMsg);
			}
		}

		//按key值对errorList排序并将value拼接成字符串
		String rs = "";
		rs += sortAndSpliceMap(errorList);
		return rs;
//		if (!StringUtil.isNullorBank(rs)) {
//			rs = "DataDuplicateError:" + rs;
//			throw new Exception(rs);
//		}
	}

	private String sortAndSpliceMap(Map<Integer, String> errorList) {
		String rs = "";
		//取出key值，根据key值排序
		Object[] key = errorList.keySet().toArray();
		Arrays.sort(key);
		//拼接信息
		Iterator ite = errorList.entrySet().iterator();
		while (ite.hasNext()) {
			Map.Entry string = (Map.Entry) ite.next();
			StringBuffer buffer = new StringBuffer();
			if (StringUtil.isNullorBank(rs)) {
				rs = (String) string.getValue();
			} else {
				rs = buffer.append(rs).append(",").append(string.getValue()).toString();
			}
		}
		return rs;
	}

	private boolean checkDataIsUnique(CusRelCheckExcelVO item) throws Exception {
		List<CusRelCheckVO> queryRs = cusRelCheckService.queryConditions(item.getCertCode(),SDicCertTypeEnum.IDCARD.getValue());
		if (Objects.isNull(queryRs) || queryRs.isEmpty()){
		    return false;
        }
		return true;
	}

	/**
	 * 从HttpServletRequest中获取文件
	 * @author  qiuyf
	 * @since 2019年3月22日 上午10:50:31
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	@SuppressWarnings("rawtypes")
	private List<File> getFileList(HttpServletRequest request) throws IOException{
		List<File> listFiles = new ArrayList<File>();
		CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver(request.getSession().getServletContext());
		if(multipartResolver.isMultipart(request)){
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator iter = multiRequest.getFileNames();
			while(iter.hasNext()) {
				MultipartFile mFile = multiRequest.getFile(iter.next().toString());
				if(mFile != null){
					listFiles.add(multipartToFile(mFile));
				}
			}
		}
		return listFiles;
	}

	/**
	 * 转换文件
	 * @author  qiuyf
	 * @since 2019年3月22日 上午11:09:26
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	private File multipartToFile(MultipartFile multfile) throws IOException {  
		CommonsMultipartFile cmf = (CommonsMultipartFile)multfile;   
		DiskFileItem dfi = (DiskFileItem) cmf.getFileItem();  
		File file = dfi.getStoreLocation();  
		if(file.length() < 2048){  
			File tmpFile = new File(System.getProperty("java.io.tmpdir") + System.getProperty("file.separator") +  file.getName());  
			multfile.transferTo(tmpFile);  
			return tmpFile;  
		}  
		return file;  
	}  

	/**
	 * 过滤null、空字符串、不合规的身份证号
	 * 0.2: qiuyf:2019年5月8日 上午11:42:45:TODO <br>
	 * @author  qiuyf
	 * @since 2019年5月8日 上午11:42:45
	 * @date 2019年5月8日 上午11:42:45
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	private List<CusRelCheckExcelVO> filterCusRelCheck(List<CusRelCheckExcelVO> cusRelCheckExcelVOList){
		List<CusRelCheckExcelVO> result = new ArrayList<>();
		Iterator<CusRelCheckExcelVO> iterator = cusRelCheckExcelVOList.iterator();
		while (iterator.hasNext()) {
			CusRelCheckExcelVO temp = iterator.next();
			if(StringUtil.isStrNotEmpty(temp.getCertCode())) {
				try {
					MessageRuleCheckUtil.validateIdNo18(temp.getCertCode());
					result.add(temp);
				} catch (BizException e) {
					logger.error("身份证号："+ temp.getCertCode() + "校验不合规！", e.getMessage());
					e.printStackTrace();
				}
			}
		}
		return result;
	}

	/**
	 * 插入关联人信息
	 * TODO <br>
	 * 0.2: qiuyf:2019年5月15日 上午11:26:33:TODO <br>
	 * @author  qiuyf
	 * @since 2019年5月15日 上午11:26:33
	 * @date 2019年5月15日 上午11:26:33
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	/*private int insertCusRelCheckData(List<CusRelCheckExcelVO> cusRelCheckExcelVOList) throws Exception{
		Iterator<CusRelCheckExcelVO> iterator = cusRelCheckExcelVOList.iterator();
		int repeatNum = 0;
		while(iterator.hasNext()) {
			CusRelCheckExcelVO tempExcelVO = iterator.next();
			CusRelCheckVO cusRelCheckVO = new CusRelCheckVO();
			//设置流水号
			cusRelCheckVO.setRelSerno(sequenceService.getSequence("CUS_REL_SERNO", null, null));
			//设置姓名
			cusRelCheckVO.setCusName(tempExcelVO.getCusName());
			//设置证件类型【需求只有居民身份证】
			cusRelCheckVO.setCertType(SDicCertTypeEnum.IDCARD.getValue());
			//设置证件号码
			cusRelCheckVO.setCertCode(tempExcelVO.getCertCode());
			//设置关联关系为  02  ： 关联人 
			cusRelCheckVO.setRelRelation(CusRelCheckEnum.CusRelRelation.CUS_ASSOCIATES.getValue());
			//设置银监会标准
			cusRelCheckVO.setCbrcStandard(tempExcelVO.getCbrcStandard());
			//设置录入时间
			cusRelCheckVO.setCreateTime(TimeUtil.getCurrentDateTime());

			int num = cusRelCheckService.insertCusRelCheckExp(cusRelCheckVO);
			try {
				cusRelCheckService.insertCusRelCheckExp(cusRelCheckVO);
			} catch (Exception e) {
				logger.error("********************************************插入数据出错，异常信息为：", e.getMessage());
				repeatNum++;
				throw new Exception("插入数据出错");
			}
		}
		return repeatNum;
	}*/

	/**
	 * 根据主键批量删除信息
	 *
	 * @param cusRelCheckVo
	 * @return
	 */
	@RequestMapping(value = "/cus/relChecks/rels", method = RequestMethod.DELETE)
	public @ResponseBody ResponseData<Integer> batchDeleteByPk(@RequestBody CusRelCheckVO cusRelCheckVo) {
		int outputVo = cusRelCheckService.batchDeleteByPk(cusRelCheckVo);
		return getResponseData(outputVo);

	}

	private List<CusRelCheckVO> dealResultShow(List<CusRelCheckVO> output){
		if(Objects.isNull(output) || output.isEmpty()){
			return output;
		}else{
			output.forEach(cusRelCheckVO -> {
				String cusName = cusRelCheckVO.getCusName();
				String certCode = cusRelCheckVO.getCertCode();
				if(StringUtil.isStrNotEmpty(cusName)){
					cusRelCheckVO.setCusName(StringUtils.overlay(cusName, getOverlay(cusName.length()-1), 1, cusName.length()));
				}
				if(StringUtil.isStrNotEmpty(certCode)){
					cusRelCheckVO.setCertCode(StringUtils.overlay(certCode, getOverlay(certCode.length()-7), 3, certCode.length()-4));
				}
			});
			return output;
		}
	}
	private String getOverlay(int total){
		String result = "";
		for (int i=0; i<total; i++){
			result+="*";
		}
		return result;
	}
}
